home *** CD-ROM | disk | FTP | other *** search
- //------------------------------------------------------------------------------
- // File: BltAlpha.h
- //
- // Desc: DirectShow sample code - implementation of CAlphaBlt class.
- //
- // Copyright (c) 1994 - 2001, Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------------------------
-
-
- #ifndef __INITDDSTRUCT_DEFINED
- #define __INITDDSTRUCT_DEFINED
- template <typename T>
- __inline void INITDDSTRUCT(T& dd)
- {
- ZeroMemory(&dd, sizeof(dd));
- dd.dwSize = sizeof(dd);
- }
- #endif
-
- #ifndef __RELEASE_DEFINED
- #define __RELEASE_DEFINED
- template<typename T>
- __inline void RELEASE( T* &p )
- {
- if( p ) {
- p->Release();
- p = NULL;
- }
- }
- #endif
-
- #ifndef CHECK_HR
- #define CHECK_HR(expr) do { if (FAILED(expr)) __leave; } while(0);
- #endif
-
-
- class CAlphaBlt
- {
- private:
-
- LPDIRECTDRAW7 m_pDD;
- LPDIRECT3D7 m_pD3D;
- LPDIRECT3DDEVICE7 m_pD3DDevice;
- LPDIRECTDRAWSURFACE7 m_lpDDBackBuffer;
-
- LPDIRECTDRAWSURFACE7 m_lpDDMirror;
- LPDIRECTDRAWSURFACE7 m_lpDDM32;
- LPDIRECTDRAWSURFACE7 m_lpDDM16;
- DDSURFACEDESC2 m_ddsdM32;
- DDSURFACEDESC2 m_ddsdM16;
-
- bool m_fPowerOf2;
- bool m_fSquare;
-
- //
- // IsSurfaceBlendable
- //
- // Checks the DD surface description and the given
- // alpha value to determine if this surface is blendable.
- //
- bool
- IsSurfaceBlendable(
- DDSURFACEDESC2& ddsd,
- BYTE fAlpha
- )
- {
- //
- // Is the blend really a blend ?
- //
-
- //if (fAlpha == 0 || fAlpha == 255) {
- // return true;
- //}
-
- //
- // Is the surface already a D3D texture ?
- //
- if (ddsd.ddsCaps.dwCaps & DDSCAPS_TEXTURE) {
- return true;
- }
-
- //
- // OK we have to mirror the surface
- //
-
- return false;
- }
-
- //
- // MirrorSourceSurface
- //
- // The mirror surface can be either 16 or 32 bit RGB depending
- // upon the format of the source surface.
- //
- // Of course it should have the "texture" flag
- // set and should be in VRAM. If we can't create the
- // surface then the AlphaBlt should fail
- //
- HRESULT MirrorSourceSurface(
- LPDIRECTDRAWSURFACE7 lpDDS,
- DDSURFACEDESC2& ddsd
- )
- {
- HRESULT hr = DD_OK;
- DWORD dwMirrorBitDepth = 0;
- DDSURFACEDESC2 ddsdMirror={0};
-
-
- //
- // OK - is it suitable for our needs.
- //
- // The following rules apply:
- // if ddsd is a FOURCC surface the mirror should be 32 bit
- // if ddsd is RGB then the mirror's bit depth should match that of ddsd.
- //
- // Also, the mirror must be large enough to actually hold
- // the surface to be blended
- //
-
- m_lpDDMirror = NULL;
-
- if (ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ||
- ddsd.ddpfPixelFormat.dwRGBBitCount == 32) {
-
- if (ddsd.dwWidth > m_ddsdM32.dwWidth ||
- ddsd.dwHeight > m_ddsdM32.dwHeight) {
-
- RELEASE(m_lpDDM32);
- }
-
- if (!m_lpDDM32) {
- dwMirrorBitDepth = 32;
- }
- else {
- m_lpDDMirror = m_lpDDM32;
- ddsdMirror = m_ddsdM32;
- }
- }
- else if (ddsd.ddpfPixelFormat.dwRGBBitCount == 16) {
-
- if (ddsd.dwWidth > m_ddsdM16.dwWidth ||
- ddsd.dwHeight > m_ddsdM16.dwHeight) {
-
- RELEASE(m_lpDDM16);
- }
-
- if (!m_lpDDM16) {
- dwMirrorBitDepth = 16;
- }
- else {
- m_lpDDMirror = m_lpDDM16;
- ddsdMirror = m_ddsdM16;
- }
- }
- else {
-
- // No support for RGB24 or RGB8 !
- return E_INVALIDARG;
- }
-
- if (!m_lpDDMirror) {
-
- INITDDSTRUCT(ddsdMirror);
- ddsdMirror.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
- ddsdMirror.ddpfPixelFormat.dwFlags = DDPF_RGB;
- ddsdMirror.ddpfPixelFormat.dwRGBBitCount = dwMirrorBitDepth;
-
- switch (dwMirrorBitDepth) {
- case 16:
- ddsdMirror.ddpfPixelFormat.dwRBitMask = 0x0000F800;
- ddsdMirror.ddpfPixelFormat.dwGBitMask = 0x000007E0;
- ddsdMirror.ddpfPixelFormat.dwBBitMask = 0x0000001F;
- break;
-
- case 32:
- ddsdMirror.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
- ddsdMirror.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
- ddsdMirror.ddpfPixelFormat.dwBBitMask = 0x000000FF;
- break;
- }
-
- ddsdMirror.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE;
- ddsdMirror.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
-
- if (m_fPowerOf2) {
-
- for (ddsdMirror.dwWidth = 1;
- ddsd.dwWidth > ddsdMirror.dwWidth;
- ddsdMirror.dwWidth <<= 1);
-
- for (ddsdMirror.dwHeight = 1;
- ddsd.dwHeight > ddsdMirror.dwHeight;
- ddsdMirror.dwHeight <<= 1);
- }
- else {
- ddsdMirror.dwWidth = ddsd.dwWidth;
- ddsdMirror.dwHeight = ddsd.dwHeight;
- }
-
- if (m_fSquare) {
-
- if (ddsdMirror.dwHeight > ddsdMirror.dwWidth) {
- ddsdMirror.dwWidth = ddsdMirror.dwHeight;
- }
-
- if (ddsdMirror.dwWidth > ddsdMirror.dwHeight) {
- ddsdMirror.dwHeight = ddsdMirror.dwWidth;
- }
- }
-
- __try {
-
- // Attempt to create the surface with theses settings
- CHECK_HR(hr = m_pDD->CreateSurface(&ddsdMirror, &m_lpDDMirror, NULL));
-
- INITDDSTRUCT(ddsdMirror);
- CHECK_HR(hr = m_lpDDMirror->GetSurfaceDesc(&ddsdMirror));
-
- switch (dwMirrorBitDepth) {
- case 16:
- m_ddsdM16 = ddsdMirror;
- m_lpDDM16 = m_lpDDMirror;
- break;
-
- case 32:
- m_ddsdM32 = ddsdMirror;
- m_lpDDM32 = m_lpDDMirror;
- break;
- }
-
- } __finally {}
- }
-
- if (hr == DD_OK) {
-
- //ASSERT(m_lpDDMirror != NULL);
-
- __try {
- RECT rc = {0, 0, ddsd.dwWidth, ddsd.dwHeight};
- CHECK_HR(hr = m_lpDDMirror->Blt(&rc, lpDDS, &rc, DDBLT_WAIT, NULL));
- ddsd = ddsdMirror;
- } __finally {}
- }
-
- return hr;
- }
-
- public:
-
- ~CAlphaBlt()
- {
- RELEASE(m_lpDDBackBuffer);
- RELEASE(m_lpDDM32);
- RELEASE(m_lpDDM16);
-
- RELEASE(m_pD3DDevice);
- RELEASE(m_pD3D);
- RELEASE(m_pDD);
- }
-
- CAlphaBlt(LPDIRECTDRAWSURFACE7 lpDDSDst, HRESULT* phr) :
- m_pDD(NULL),
- m_pD3D(NULL),
- m_pD3DDevice(NULL),
- m_lpDDBackBuffer(NULL),
- m_lpDDMirror(NULL),
- m_lpDDM32(NULL),
- m_lpDDM16(NULL),
- m_fPowerOf2(false),
- m_fSquare(false)
- {
-
- ZeroMemory(&m_ddsdM32, sizeof(m_ddsdM32));
- ZeroMemory(&m_ddsdM16, sizeof(m_ddsdM16));
-
- HRESULT hr;
- hr = lpDDSDst->GetDDInterface((LPVOID *)&m_pDD);
- if (FAILED(hr)) {
- m_pDD = NULL;
- *phr = hr;
- }
-
- if (SUCCEEDED(hr)) {
- hr = m_pDD->QueryInterface(IID_IDirect3D7, (LPVOID *)&m_pD3D);
- if (FAILED(hr)) {
- m_pD3D = NULL;
- *phr = hr;
- }
- }
-
- if (SUCCEEDED(hr)) {
- hr = m_pD3D->CreateDevice(IID_IDirect3DHALDevice,
- lpDDSDst,
- &m_pD3DDevice);
- if (FAILED(hr)) {
- m_pD3DDevice = NULL;
- *phr = hr;
- }
- else {
- m_lpDDBackBuffer = lpDDSDst;
- m_lpDDBackBuffer->AddRef();
- }
- }
-
- if (SUCCEEDED(hr)) {
-
- D3DDEVICEDESC7 ddDesc;
- if (DD_OK == m_pD3DDevice->GetCaps(&ddDesc)) {
-
- if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) {
- m_fPowerOf2 = true;
- }
-
- if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) {
- m_fSquare = true;
- }
- }
- else {
- *phr = hr;
- }
- }
- }
-
- HRESULT
- AlphaBlt(RECT* lpDst,
- LPDIRECTDRAWSURFACE7 lpDDSSrc,
- RECT* lpSrc,
- BYTE bAlpha
- )
- {
- HRESULT hr=S_OK;
- DDSURFACEDESC2 ddsd;
-
- struct {
- float x, y, z, rhw;
- D3DCOLOR clr;
- float tu, tv;
- } pVertices[4];
-
- __try {
-
- INITDDSTRUCT(ddsd);
- CHECK_HR(hr = lpDDSSrc->GetSurfaceDesc(&ddsd));
-
- if (!IsSurfaceBlendable(ddsd, bAlpha)) {
- CHECK_HR(hr = MirrorSourceSurface(lpDDSSrc, ddsd));
- lpDDSSrc = m_lpDDMirror;
- }
-
- float fWid = (float)ddsd.dwWidth;
- float fHgt = (float)ddsd.dwHeight;
-
- BYTE alpha = bAlpha;
-
- //
- // Setup the DST info
- //
- pVertices[0].x = (float)lpDst->left;
- pVertices[0].y = (float)lpDst->top;
- pVertices[0].z = 0.5f;
- pVertices[0].rhw = 2.0f;
- pVertices[0].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
-
- pVertices[1].x = (float)lpDst->right;
- pVertices[1].y = (float)lpDst->top;
- pVertices[1].z = 0.5f;
- pVertices[1].rhw = 2.0f;
- pVertices[1].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
-
- pVertices[2].x = (float)lpDst->left;
- pVertices[2].y = (float)lpDst->bottom;
- pVertices[2].z = 0.5f;
- pVertices[2].rhw = 2.0f;
- pVertices[2].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
-
- pVertices[3].x = (float)lpDst->right;
- pVertices[3].y = (float)lpDst->bottom;
- pVertices[3].z = 0.5f;
- pVertices[3].rhw = 2.0f;
- pVertices[3].clr = RGBA_MAKE(0xff, 0xff, 0xff, alpha);
-
- //
- // Setup the SRC info
- //
- pVertices[0].tu = (float)lpSrc->left / fWid;
- pVertices[0].tv = (float)lpSrc->top / fHgt;
-
- pVertices[1].tu = (float)lpSrc->right / fWid;
- pVertices[1].tv = (float)lpSrc->top / fHgt;
-
- pVertices[2].tu = (float)lpSrc->left / fWid;
- pVertices[2].tv = (float)lpSrc->bottom / fHgt;
-
- pVertices[3].tu = (float)lpSrc->right / fWid;
- pVertices[3].tv = (float)lpSrc->bottom / fHgt;
-
- //
- // Setup some random D3D stuff
- //
- m_pD3DDevice->SetTexture(0, lpDDSSrc);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, FALSE);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_BLENDENABLE, TRUE);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
-
- // use diffuse alpha from vertices, not texture alpha
- // m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
-
- m_pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
- m_pD3DDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
- m_pD3DDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTFN_LINEAR);
- m_pD3DDevice->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTFP_LINEAR);
- m_pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
-
- m_pD3DDevice->SetTextureStageState( 0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
-
- //
- // Do the alpha BLT
- //
- CHECK_HR(hr = m_pD3DDevice->BeginScene());
- CHECK_HR(hr = m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
- D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1,
- pVertices, 4, D3DDP_WAIT));
- CHECK_HR(hr = m_pD3DDevice->EndScene());
-
- } __finally {
- m_pD3DDevice->SetTexture(0, NULL);
- }
-
- return hr;
- }
-
- bool TextureSquare() {
- return m_fSquare;
- }
-
- bool TexturePower2() {
- return m_fPowerOf2;
- }
- };
-